﻿using FlaUI.Core.AutomationElements;
using FlaUI.UIA3;
using Flurl.Http;
using Ice;
using Ice.Extension;
using IndustrialSwitchWriteMac.Core;
using Instances;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace IndustrialSwitchWriteMac
{
    public partial class Form1 : Form
    {
        private readonly string _version = "D20251105B";
        private Config _config;
        private string _upgradeLog = "";
        private string _applicationName;
        private Stopwatch _sw = new Stopwatch();
        private Stopwatch _totalSw = new Stopwatch();


        //OKmac
        private List<string> _passMacs = new List<string>();

        private List<string> _itemValues = new List<string>();

        private string _log = "";
        private CancellationTokenSource _cts;

        private IProcessInstance _pingInstance;

        private FlurlClient _flurlClient = new FlurlClient();
        private ManualResetEvent _manualResetEvent = new ManualResetEvent(true);

        public Form1()
        {
            this.StartPosition = FormStartPosition.CenterScreen;
            _config = IniHelper.GetConfig();
            InitializeComponent();
            this.FormClosed += (o, e) =>
            {
                try
                {
                    _pingInstance?.Kill();
                }
                catch
                {
                }
                Environment.Exit(0);
            };
            tboxMac.KeyDown += textbox_keyDown;

            _applicationName = Process.GetCurrentProcess().ProcessName + ".exe";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.MinimizeBox = false;
            this.MaximizeBox = false;
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.toolStripStatusLabel1.Text = "软件版本:" + _version;
            this.Text = string.IsNullOrEmpty(_config.Title) ? "工业级交换机写MAC" : _config.Title;


            _sw.Start();

            LoadPassMac();
            ShowInfo("请先点击开始!");
            tboxMac.Visible = true;
            ttt12.Visible = true;
            this.ActiveControl = tboxMac;
        }



        private void AddRow(string content, string result)
        {
            _sw.Restart();
            dataGridView1.Invoke(x =>
            {
                var i = x.Rows.Count;
                x.Rows.Add(i + 1, content, result, "");
            });
        }

        private void UpdateRow(bool result)
        {
            var secord = _sw.ElapsedMilliseconds * 1.0 / 1000;
            dataGridView1.Invoke(x =>
            {
                var i = x.Rows.Count;
                x[2, i - 1].Value = result ? "✔" : "NG";
                x[2, i - 1].Style.ForeColor = result ? Color.Green : Color.Red;
                x[3, i - 1].Value = secord.ToString("0.00");
            });
        }


        private void WriteLog(string mac, bool result, string data1, string data2)
        {
            var dir = _config.LogDir;
            dir = Path.Combine(dir, Text + $"({_applicationName})", DateTime.Now.ToString("yyyyMMdd"));
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            //var secord = _totalSw.ElapsedMilliseconds * 1.0 / 1000;
            //_totalSw.Stop();
            //AddRow("总耗时", secord.ToString());
            //var log = _upgradeLog + _log + Environment.NewLine + $"结束时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss} 总耗时:{secord} 秒";
            //var s = result ? "logO" : "logX";
            //var name = _config.Title ?? "";
            //var filename = Path.Combine(dir, $"{name}_{s}_{mac.ToMesMac()}_{DateTime.Now:yyyyMMddHHmmss}.txt");
            //File.WriteAllText(filename, log);

            //csv
            var csvDir = Path.Combine(dir, "csv日志");
            if (!Directory.Exists(csvDir)) Directory.CreateDirectory(csvDir);
            var csvFile = $"{DateTime.Now:yyyyMMdd}.csv";
            if (!File.Exists(Path.Combine(csvDir, csvFile)))
            {
                File.WriteAllText(Path.Combine(csvDir, csvFile), "No,MAC,Test Result,Data1,Data2" + Environment.NewLine);
            }
            var lines = File.ReadAllLines(Path.Combine(csvDir, csvFile));
            int i = lines.Length;
            File.AppendAllText(Path.Combine(csvDir, csvFile), $"{i},{mac.AddColon()}," + (result ? "OK" : "NG") + $",{data1},{data2}" + Environment.NewLine);
        }


        private delegate void InvokeDelegate();
        /// <summary>
        /// 同步更新UI
        /// </summary>
        /// <param name="invoke"></param>
        private void postUI(InvokeDelegate invoke)
        {
            this.Invoke(invoke);
        }

        private void textbox_keyDown(object sender, KeyEventArgs e)
        {

            if (e.KeyCode == Keys.Enter)
            {
                System.Windows.Forms.TextBox tb = (System.Windows.Forms.TextBox)sender;
                if (tb == tboxMac)
                {
                    string mac = tboxMac.Text.ToMesMac();
                    if (!mac.CheckMacLength())
                    {
                        return;
                    }
                    if (!mac.ToUpper().StartsWith(_config.MacPrefix.ToUpper()))
                    {
                        MessageBox.Show("MAC前6位不匹配,请检查");
                        return;
                    }
                    if (_passMacs.Any(w => w.ToMesMac() == mac))
                    {
                        ShowInfo($"{tboxMac.Text}\n不能重复核对NG", false);
                        tboxMac.Focus();
                        tboxMac.Text = "";
                        return;
                    }
                    _log = "";
                    ShowInfo("正在写入MAC");
                    tboxMac.Enabled = false;
                    button2.Enabled = false;
                    dataGridView1.Rows.Clear();
                    Task.Run(async () =>
                    {
                        try
                        {
                            _totalSw.Restart();
                            AppendConsoleInfo($"开始时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
                            if (_config.SwitchType == "L-2008") await WriteMacAsync();
                            if (_config.SwitchType == "L-2226F") await WriteL2226FMacAsync();
                        }
                        catch (Exception ex)
                        {
                            ShowInfo(ex.ToString(), false);
                        }
                        finally
                        {
                            this.Invoke(new Action(delegate
                            {
                                this.Activate();
                                button2.Enabled = true;
                                tboxMac.Enabled = true;
                                tboxMac.Focus();
                                tboxMac.SelectAll();
                            }));
                        }
                    });
                }
            }
        }


        private async Task WriteMacAsync()
        {
            var mac = tboxMac.Text.ToMesMac();
            mac = mac.AddColon();
            AddRow("写入MAC:" + mac, "写入中");
            var url = $"http://{_config.Ip}/mac.cgi?page=setmac&addr={mac}";
            var s = await _flurlClient.Request(url).WithBasicAuth(_config.Account, _config.Password).GetStringAsync();

            if (s.Contains(mac))
            {
                WriteLog(mac.ToMesMac(), true, url, s);
                UpdateRow(true);
                ShowInfo("写入MAC\nPASS", true);
                return;
            }
            WriteLog(mac.ToMesMac(), false, url, s);
            UpdateRow(false);
            ShowInfo("写入MAC\nNG", false);
        }

        /// <summary>
        /// L-2226F写MAC
        /// </summary>
        /// <returns></returns>
        private async Task WriteL2226FMacAsync()
        {
            var mac = tboxMac.Text.ToMesMac();
            mac = mac.AddColon();
            AddRow("写入MAC:" + mac, "写入中");
            Dos.RunCmd("taskkill /im macBurn.exe /f");

            //var localMac = GetLocalMac();
            //if (string.IsNullOrEmpty(localMac))
            //{
            //    UpdateRow(false);
            //    ShowInfo("找不到本地网卡\n请检查设置的本地IP是否正确", false);
            //    return;
            //}

            var app = FlaUI.Core.Application.Launch(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "macBurn_tool_RTL8370N", "macBurn.exe"));
            await Task.Delay(1500);
            using (var automation = new UIA3Automation())
            {
                var window = app.GetMainWindow(automation);
                //点击check
                var checkBtn = window.FindFirstDescendant(cf => cf.ByText("Check"))?.AsButton();
                checkBtn.Click();

                var children = window.FindAllChildren();

                var panel1 = children[2]; //设置区
                var orderTxt = panel1.FindAllChildren().Where(w => w.ControlType == FlaUI.Core.Definitions.ControlType.Edit).Last().AsTextBox();
                orderTxt.Text = "1";

                window.FindFirstDescendant(cf => cf.ByText("SetOrder"))?.AsButton().Click();
                await Task.Delay(1000);
                window.FindFirstDescendant(cf => cf.ByText("OK"))?.AsButton().Click();



                //var resultTxt = children[1].FindAllChildren().Where(w => w.ControlType == FlaUI.Core.Definitions.ControlType.Edit).Last().AsTextBox();

                //设置mac
                var macTxts = children[0].FindAllChildren().Where(w => w.ControlType == FlaUI.Core.Definitions.ControlType.Edit).Reverse();
                var maxMacTxts = macTxts.Take(6).ToList();
                var minMacTxts = macTxts.Skip(6).Take(6).ToList();

                var macArr = mac.Split(':');
                for (int i = 0; i < macArr.Length; i++)
                {
                    var txt = minMacTxts[i].AsTextBox();
                    txt.Text = macArr[i];

                    txt = maxMacTxts[i].AsTextBox();
                    txt.Text = macArr[i];
                }

                window.FindFirstDescendant(cf => cf.ByText("SetRange"))?.AsButton().Click();
                await Task.Delay(500);
                window.FindFirstDescendant(cf => cf.ByText("Yes"))?.AsButton().Click();
                await Task.Delay(500);
                window.FindFirstDescendant(cf => cf.ByText("OK"))?.AsButton().Click();

                //点击稍等
                window.FindFirstDescendant(cf => cf.ByText("BurnMAC"))?.AsButton().Click();

                int k = 20;
                string result = "";
                Window win = null;
                while (k > 0)
                {
                    await Task.Delay(500);
                    win = window.FindAllChildren().FirstOrDefault()?.AsWindow();
                    if (win != null) break;
                    k--;
                }
                if (win == null)
                {
                    UpdateRow(false);
                    ShowInfo("写入MAC\nNG", false);
                }
                await Task.Delay(800);

                
                win = window.FindAllChildren().First().AsWindow();

                result = win.FindFirstDescendant(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Text)).AsLabel().Text;
                win.FindFirstDescendant(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Button)).AsButton().Click();

                if (result.ToLower().Contains("ok"))
                {
                    WriteLog(mac.ToMesMac(), true, "", "");
                    UpdateRow(true);
                    ShowInfo("写入MAC\nPASS", true);
                    return;
                }
            }
            // app.Close();
            //var s = "";
            //if (s.Contains(mac))
            //{
            //    WriteLog(mac.ToMesMac(), true, url, s);
            //    UpdateRow(true);
            //    ShowInfo("写入MAC\nPASS", true);
            //    return;
            //}
            //WriteLog(mac.ToMesMac(), false, url, s);
            UpdateRow(false);
            ShowInfo("写入MAC\nNG", false);
        }

        private string GetLocalMac()
        {
            NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in adapters)
            {
                var mac = adapter.GetPhysicalAddress().ToString(); // mac  18C04D6C6C91
                                                                   //System.Console.WriteLine(mac);

                var addresses = adapter.GetIPProperties().UnicastAddresses;
                foreach (var item in addresses)
                {
                    if (item.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) continue;
                    var ip = item.Address.ToString();
                    System.Console.WriteLine($"{adapter.Name} mac:{mac} ip:{ip}");
                    if (ip == _config.LocalIp) return mac;
                }
            }
            return "";
        }

        private void EnableMac()
        {
            tboxMac.Invoke(x =>
            {
                button2.Enabled = true;
                tboxMac.Enabled = true;
                tboxMac.Focus();
                tboxMac.SelectAll();
            });
        }


        private void AppendConsoleInfo(string s)
        {
            tboxPing.Invoke(x =>
            {
                //x.AppendText(Environment.NewLine + s + Environment.NewLine);
                _log += s + Environment.NewLine;
            });
        }

        private void ShowInfo(string info)
        {
            this.postUI(() =>
            {
                labShow.Text = info;
                labShow.ForeColor = Color.Black;
            });
        }

        private void ShowInfo(string info, bool flag)
        {
            this.postUI(() =>
            {
                labShow.Text = info;
                labShow.ForeColor = flag ? Color.Green : Color.Red;
            });
        }


        private void Button2_Click(object sender, EventArgs e)
        {
            var f = new ConfigForm();
            if (f.ShowDialog() == DialogResult.OK)
            {
                _config = IniHelper.GetConfig();
                Text = _config.Title;
                ttt12.Text = "MAC:";
                tboxMac.Text = "";
            }
        }

        private void SavePassMac(string mac)
        {
            _passMacs.Add(mac.ToMesMac());
            File.AppendAllLines("pass_mac.txt", new string[] { mac.ToMesMac() });
        }

        private void LoadPassMac()
        {
            if (!File.Exists("pass_mac.txt")) return;
            var macs = File.ReadAllLines("pass_mac.txt");
            _passMacs = macs.Where(w => !string.IsNullOrEmpty(w)).ToList();
        }

        static void RestartApp()
        {
            // 获取当前执行的exe文件的路径
            string exePath = Assembly.GetExecutingAssembly().Location;

            // 启动新的进程来运行当前exe文件
            Process.Start(exePath);

            // 关闭当前进程
            Environment.Exit(0);
        }


        private void btnStart_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(_config.Ip))
            {
                MessageBox.Show("请先维护IP地址");
                return;
            }
            if (btnStart.Text == "开始")
            {

                var processArgument = new ProcessArguments("ping", $"{_config.Ip} -t");
                processArgument.OutputDataReceived += ProcessArgument_OutputDataReceived;
                _pingInstance = processArgument.Start();

                _cts = new CancellationTokenSource();
                tboxMac.Enabled = false;
                Task.Factory.StartNew(ThreadPing, TaskCreationOptions.LongRunning);
                button2.Enabled = false;
                btnStart.Text = "停止";
                ShowInfo("等待设备连接!");
            }
            else
            {
                _pingInstance?.Kill();
                _cts.Cancel();
                button2.Enabled = true;
                btnStart.Text = "开始";
                ShowInfo("");
            }
        }

        private void ProcessArgument_OutputDataReceived(object sender, string e)
        {
            tboxPing.Invoke(x =>
            {
                x.AppendText(e + Environment.NewLine);
                x.ScrollToCaret();
            });
        }

        private void ThreadPing()
        {
            var ping = new Ping();
            var flag = true;
            int count = 0;
            var ip = _config.Ip;
            while (!_cts.IsCancellationRequested)
            {
                // _manualResetEvent.WaitOne();
                PingReply pRelay = null;
                try
                {
                    pRelay = ping.Send(ip, 800);
                }
                catch
                {
                }
                //if (pRelay == null) continue;
                if (pRelay != null && pRelay.Status == IPStatus.Success)
                {
                    if (flag)
                    {
                        count++;
                    }
                    if (flag && count > 2 && ip.CheckPort(80))
                    {
                        count = 0;
                        this.postUI(() =>
                        {
                            tboxMac.Enabled = true;
                            tboxMac.Text = "";
                            tboxMac.Focus();
                            ShowInfo("请扫入信息");
                            dataGridView1.Rows.Clear();
                        });
                        flag = false;
                    }
                }
                else
                {
                    if (!flag)
                    {
                        count++;
                    }
                    if (!flag && count > 4)
                    {
                        flag = true;
                        this.postUI(() =>
                        {
                            tboxMac.Text = "";
                            tboxMac.Enabled = false;
                            dataGridView1.Rows.Clear();
                        });
                        ShowInfo("等待设备连接!");
                    }
                }
                Task.Delay(400, _cts.Token).Wait();
            }
        }

        private void btnCheck_Click(object sender, EventArgs e)
        {
            textbox_keyDown(tboxMac, new KeyEventArgs(Keys.Enter));
        }
    }
}
